require "Common/define"
require "Logic/Config"
require "Common/functions"
---@class RealManWarManager
RealManWarManager = RealManWarManager or {};
local this = RealManWarManager;

local loadNum = 0;
local skeletonAnimStateUserDataString = {}

function RealManWarManager.init()
    this.isAutoBattle = false;
end

function RealManWarManager.OnDestroy()
    this.fightResult = nil;
    this.realManPlayerInfo = nil;
    this.isAutoBattle = false;
end

-- 自动战斗
function RealManWarManager.getPlayerOperationState()
    return this.isAutoBattle;
end

function RealManWarManager.setPlayerOperationState(value)
    this.isAutoBattle = value;
    if value then
        SetPlayerPrefs("UISoloBattleAuto" .. logicMgr.HeroManager.GetRoleInfo("playerId"), 1);
    else
        SetPlayerPrefs("UISoloBattleAuto" .. logicMgr.HeroManager.GetRoleInfo("playerId"), 0);
    end
end

function RealManWarManager.getOpenType()
    return this.localOpenType;
end

function RealManWarManager.getEnterBattle()
    return this.hasEnterBattle or false;
end

function RealManWarManager.setEnterBattle(value)
    this.hasEnterBattle = value;
end

-- 更新打开类页签红点状态
function RealManWarManager.updateRealManOpenStatus()
    if GetPlayerPrefsAfter5AMFlag("realManWar") then
        SetPlayerPrefsAfter5AMFlag("realManWar");
        FireEvent(Config.EventType.Fresh_RealManRed);
    end
end

function RealManWarManager.getRealManOpenStatus()
    if this.isOpen() and GetPlayerPrefsAfter5AMFlag("realManWar") then
        return true;
    else
        return false;
    end
end

function RealManWarManager.setGetData(value)
    this.isGetData = value;
end

function RealManWarManager.OpenSoloBattle(openType)
    if this.isGetData ~= nil and this.isGetData then
        return;
    end
    this.localOpenType = openType or this.localOpenType; --1,是城外，其他是冒险
    if this.realManWarInfo == nil then
        this.isGetData = false;
        print("没有赛季信息");
        return;
    end
    if this.realManPlayerInfo == nil then
        --请求数据
        this.isGetData = true;
        RealManWarHandler.sendReqRealManFuckInfoMessage();
    else
        if this.realManPlayerInfo.formation == nil or #this.realManPlayerInfo.formation < 1 or this.realManWarInfo.season ~= this.realManPlayerInfo.season then
            if this.hasEnterBattle ~= nil and this.hasEnterBattle then
                this.hasEnterBattle = false;
            else
                showUI(PanelNames.UIEnterSolo);
            end
        else
            if this.localOpenType == 3 and this.isAutoBattle then
                local battleResult = this.getFightResult();
                if battleResult ~= nil and battleResult.fightResult == 1 then
                    local cfgId = tonumber(this.GetRealManPlayerInfo().step) + 1;
                    local abyssCfg = dataTable.getDataTableByStringId("t_abyss", cfgId);
                    if abyssCfg ~= nil then
                        -- 自动战斗
                        local formation = {};
                        table.insert(formation, this.GetRealManPlayerInfo().partnerId);
                        for i = 1, 5 do
                            table.insert(formation, "0");
                        end
                        BattlePlaybackManager.SetFightType(EnumConst.FightTypeConst.RealMan);
                        RealManWarHandler.sendReqHappyFuckMessage(formation, false);
                    else
                        this.setPlayerOperationState(false);
                        showUI(PanelNames.UISoloBattle);
                    end
                else
                    this.setPlayerOperationState(false);
                    showUI(PanelNames.UISoloBattle);
                end
            else
                this.setPlayerOperationState(false);
                showUI(PanelNames.UISoloBattle);
            end
        end
    end
end

function RealManWarManager.setMaxPosIndex(value)
    this.maxPosIndex = value;
end

local posIndex = 1;
function RealManWarManager.getPosIndex()
    return posIndex;
end

function RealManWarManager.setPosIndex(value)
    if value > this.maxPosIndex then
        posIndex = 1;
    else
        posIndex = value;
    end
end

-- 设置战斗状态
function RealManWarManager.setAutoBattleState(isAuto)
    if isAuto then
        if this.realManWarInfo == nil then
            SetPlayerPrefs("RealManWar", 0);
        else
            SetPlayerPrefs("RealManWar", this.realManWarInfo.nextChangeStatusTime);
        end
    else
        SetPlayerPrefs("RealManWar", 0);
    end
end

function RealManWarManager.getAutoBattleState()
    local value = GetPlayerPrefs("RealManWar");
    if value == nil then
        return false;
    end
    local serverTime = HelperFunc.GetServerTime();
    if serverTime > tonumber(value) then
        return false;
    end
    return true;
end

function RealManWarManager.getRealManWarInfo()
    return this.realManWarInfo;
end

function RealManWarManager.setRealManWarInfo(msg)
    if this.realManWarInfo == nil then
        this.realManWarInfo = {};
    end
    this.realManWarInfo.season = tonumber(msg.season);
    this.realManWarInfo.status = tonumber(msg.status);
    this.realManWarInfo.nextChangeStatusTime = tonumber(tostring(msg.nextChangeStatusTime)) * 0.001;
end

function RealManWarManager.isOpen()
    if not logicMgr.FuncOpenManager.isOpen(Config.FuncOpenType.RealMan, false) then
        return false;
    end
    if this.realManWarInfo == nil or this.realManWarInfo.status == nil or this.realManWarInfo.status == 0 or HelperFunc.GetServerTime() > this.realManWarInfo.nextChangeStatusTime then
        return false;
    end
    return true;
end

function RealManWarManager.getFightResult()
    return this.fightResult;
end

function RealManWarManager.setFightResult(msg)
    if msg == nil then
        this.fightResult = nil;
    else
        this.fightResult = {};
        this.setRealManPlayerInfo(msg.playerInfo);
        this.fightResult.fightId = msg.fightId;
        this.fightResult.fightResult = msg.fightResult;
        this.fightResult.step = msg.step;
        if msg.record ~= nil then
            this.fightResult.record = msg.record;
        else
            this.fightResult.record = nil;
        end
        if msg.reward ~= nil then
            this.fightResult.reward = {};
            this.fightResult.reward.type = tonumber(msg.reward.type);
            this.fightResult.reward.id = tonumber(msg.reward.mid);
            this.fightResult.reward.num = tonumber(tostring(msg.reward.amount));
        end
    end
end

function RealManWarManager.GetRealManPlayerInfo()
    return this.realManPlayerInfo;
end

function RealManWarManager.setRealManPlayerInfo(msg, isReward)
    --if isReward ~= nil and isReward then
    --    this.realManPlayerInfo.items = nil;
    --    return;
    --end
    if this.realManPlayerInfo == nil then
        this.realManPlayerInfo = {};
    end
    if msg.season == nil then
        this.realManPlayerInfo.season = 1;
    else
        this.realManPlayerInfo.season = tonumber(msg.season);
    end
    this.realManPlayerInfo.formation = {};
    if msg.fuckMen ~= nil then
        for i = 1, #msg.fuckMen do
            table.insert(this.realManPlayerInfo.formation, tostring(msg.fuckMen[i]));
        end
    elseif msg.formation ~= nil then
        for i = 1, #msg.formation do
            table.insert(this.realManPlayerInfo.formation, tostring(msg.formation[i]));
        end
    end
    this.realManPlayerInfo.step = tonumber(msg.step);
    if msg.partnerId == nil then
        this.realManPlayerInfo.partnerId = "";
    else
        this.realManPlayerInfo.partnerId = tostring(msg.partnerId);
    end
    this.realManPlayerInfo.myTeam = {};
    if msg.myTeam ~= nil then
        for i = 1, #msg.myTeam do
            local team = {};
            team.partnerId = tostring(msg.myTeam[i].partnerId);
            team.hp = tonumber(tostring(msg.myTeam[i].hp));
            team.maxHp = tonumber(tostring(msg.myTeam[i].maxHp));
            team.energy = tonumber(tostring(msg.myTeam[i].energy));
            this.realManPlayerInfo.myTeam[team.partnerId] = team;
        end
    end
    if this.realManPlayerInfo.armyTeam ~= nil then
        this.realManPlayerInfo.preArmyTeam = this.realManPlayerInfo.armyTeam;
    else
        this.realManPlayerInfo.preArmyTeam = {};
    end
    this.realManPlayerInfo.armyTeam = {};
    this.realManPlayerInfo.hasArmyDead = false;
    if msg.armyTeam ~= nil then
        for i = 1, #msg.armyTeam do
            local team = {};
            team.partnerId = tostring(msg.armyTeam[i].partnerId);
            team.hp = tonumber(tostring(msg.armyTeam[i].hp));
            team.maxHp = tonumber(tostring(msg.armyTeam[i].maxHp));
            team.energy = tonumber(tostring(msg.armyTeam[i].energy));
            team.needLoadHero = true;
            if team.hp == 0 and this.realManPlayerInfo.preArmyTeam[team.partnerId] ~= nil and this.realManPlayerInfo.preArmyTeam[team.partnerId].hp == 0 then
                team.needLoadHero = false;
            end
            if team.hp == 0 and (this.realManPlayerInfo.preArmyTeam[team.partnerId] == nil or (this.realManPlayerInfo.preArmyTeam[team.partnerId] ~= nil and this.realManPlayerInfo.preArmyTeam[team.partnerId].hp ~= 0)) then
                this.realManPlayerInfo.hasArmyDead = true;
            end
            this.realManPlayerInfo.armyTeam[team.partnerId] = team;
        end
    end

    if this.realManPlayerInfo.buff ~= nil then
        this.realManPlayerInfo.preBuff = this.realManPlayerInfo.buff;
    end

    if this.realManPlayerInfo.potion ~= nil then
        this.realManPlayerInfo.prePotion = this.realManPlayerInfo.potion;
    end

    this.realManPlayerInfo.buff = {};
    this.realManPlayerInfo.potion = {};
    this.realManPlayerInfo.items = nil;
    this.sweepReward = false;
    if msg.reward ~= nil then
        this.realManPlayerInfo.items = {};
        for i = 1, #msg.reward do
            local localReward = msg.reward[i];
            local type = tonumber(localReward.type);
            local id = tonumber(localReward.mid);
            local num = tonumber(tostring(localReward.amount));
            if type == 1 then
                --宝箱
                local item = {};
                item.id = id;
                item.num = num;
                table.insert(this.realManPlayerInfo.items, item);
            elseif type == 2 then
                --buff
                this.realManPlayerInfo.buff[id] = num;
            elseif type == 3 then
                --药水
                this.realManPlayerInfo.potion[id] = num;
            end
        end
        if #this.realManPlayerInfo.items > 0 then
            this.sweepReward = true;
        end
    else
        if msg.buff ~= nil then
            for i = 1, #msg.buff do
                local localBuff = msg.buff[i];
                this.realManPlayerInfo.buff[tonumber(localBuff.mid)] = tonumber(tostring(localBuff.amount));
            end
        end
        if msg.potion ~= nil then
            for i = 1, #msg.potion do
                local localPotion = msg.potion[i];
                this.realManPlayerInfo.potion[tonumber(localPotion.mid)] = tonumber(tostring(localPotion.amount));
            end
        end
    end
end

function RealManWarManager.resetArmyTeam()
    if this.realManPlayerInfo ~= nil then
        this.realManPlayerInfo.armyTeam = {};
    end
end

function RealManWarManager.hasSweepReward()
    return this.sweepReward or false;
end

function RealManWarManager.setSweepReward(value)
    this.sweepReward = value;
end

function RealManWarManager.getRealManFuckRankList()
    return this.realManRank;
end

function RealManWarManager.setRealManFuckRankList(msg)
    if this.realManRank == nil then
        this.realManRank = {};
    end
    this.realManRank.list = {};
    this.realManRank.myRank = nil;
    if this.realManPlayerInfo ~= nil then
        local myRank = {};
        myRank.playerId = logicMgr.HeroManager.GetRoleId();
        myRank.name = logicMgr.HeroManager.GetRoleName();
        myRank.headIcon = logicMgr.HeroManager.GetRoleHeadID();
        myRank.headFrame = logicMgr.HeroManager.GetRoleHeadFrame();
        myRank.level = 1;
        myRank.rank = tonumber(tostring(0));
        if this.realManPlayerInfo.step == nil or this.realManPlayerInfo.step < 1 then
            myRank.score = 1;
        else
            myRank.score = this.realManPlayerInfo.step;
        end
        this.realManRank.myRank = myRank;
    end
    if msg.rank ~= nil then
        for k,v in pairs(msg.rank) do
            local item = {};
            item.playerId = tostring(v.playerId);
            item.name = v.name;
            item.headIcon = v.headIcon;
            item.headFrame = v.headFrame;
            item.level = v.level;
            item.rank = tonumber(tostring(v.rank));
            item.score = tonumber(tostring(v.score));
            if item.playerId == logicMgr.HeroManager.GetRoleId() then
                this.realManRank.myRank = item;
            end
            table.insert(this.realManRank.list, item);
        end
    end
end

--[[
-- 指不定会用到
local isLoadScene = false;
function RealManWarManager.loadScene()
    local battleMapCfg = G.dataTable["t_solobattlemap"][tostring("1")];
    isLoadScene = true;
    resMgr:LoadModelPrefab("Prefabs/MapPref/"..battleMapCfg.f_Map, function(obj)
        local go = newObject(obj);
        this.sceneRoot = go;
        local b = go.transform:Find("Map");
        if b then
            b.gameObject:SetActive(false);
        end
        this.battleMap = go.transform:Find("BattleMap");
        local root = go.transform:GetChild(1);
        --this.farList = { MapItem.New(root:GetChild(0)) };
        --this.midList = { MapItem.New(root:GetChild(1)) };
        --this.nearList = { MapItem.New(root:GetChild(2)) };
        this.LoadDone();
    end)
    loadNum = 0;
    this.LoadFormation(4);
    this.LoadMonster(17);
end

function this.LoadDone()
    this.isLoading = false;
    local tran = this.sceneRoot.transform;
    Util.Lua_SetLocalPositionXYZ(tran, -1500, -1500, 0);
    this.CreateCamera();
    --this.ExpandScene();
end

function this.CreateCamera()
    local go = GameObject.New("camera");
    local camera = go:AddComponent(TCamera);
    camera.depth = -1;
    camera.fieldOfView = 47;

    local tran = camera.transform;
    this.cameraTran = tran;
    this.camera = camera;
    tran:SetParent(this.sceneRoot.transform, false);
    --local pos, scale = this.GetCameraPos(ExpeditionMgr.GetCurStageId());
    Util.Lua_SetLocalPositionXYZ(this.cameraTran, 293, 314, 275);
    Util.Lua_SetLocalRotationXYZ(this.cameraTran, 40.83, 0, 0);
end

function RealManWarManager.LoadFormation(modelId)
    local roleInfo = EntityInfo:new();
    roleInfo.fighterId = 1;
    roleInfo.partnerId = 1;
    roleInfo.partnerModelId = modelId;
    roleInfo.robot = false;
    roleInfo.monster = false;
    roleInfo.name = "hero";
    roleInfo.level = 1;
    roleInfo.star = 1;
    roleInfo.teamIndex = 1;
    this.hero = Entity:new(roleInfo);
    this.hero.scale = Vector3(2, 2, 2);
    this.hero:initAvatar(this.sceneRoot.transform, function()
        this.hero:setPosition(Vector3(287.5, 294, 301));
    end);
    this.hero.roleObj:SetActive(true);
    local roleCfg = G.dataTable["t_roleconfig"][tostring(modelId)];
    if roleCfg ~= nil then
        local skills = roleCfg.nomalSkill--decodeJsonStrToTabel(roleCfg.nomalSkill);
        this.hero.normalSkill = {};
        for i=1,#skills do
            if indexofTable(this.hero.normalSkill,skills[i]) <= 0 then
                table.insert(this.hero.normalSkill,skills[i]);
            end
        end
    end
    this.loadHeroEnd();
end

function RealManWarManager.LoadMonster(modelId)
    local roleInfo = EntityInfo:new();
    roleInfo.fighterId = 1;
    roleInfo.partnerId = 1;
    roleInfo.partnerModelId = modelId;
    roleInfo.robot = false;
    roleInfo.monster = false;
    roleInfo.name = "monster";
    roleInfo.level = 1;
    roleInfo.star = 1;
    roleInfo.teamIndex = 2;
    this.monster = Entity:new(roleInfo);
    this.monster.scale = Vector3(2, 2, 2);
    this.monster:initAvatar(this.sceneRoot.transform, function()
        this.monster:setPosition(Vector3(297, 294, 301));
    end);
    this.monster.roleObj:SetActive(true);
    local roleCfg = G.dataTable["t_roleconfig"][tostring(modelId)];
    if roleCfg ~= nil then
        local skills = roleCfg.nomalSkill--decodeJsonStrToTabel(roleCfg.nomalSkill);
        this.monster.normalSkill = {};
        for i=1,#skills do
            if indexofTable(this.monster.normalSkill,skills[i]) <= 0 then
                table.insert(this.monster.normalSkill,skills[i]);
            end
        end
    end
    this.loadHeroEnd();
end

function RealManWarManager.loadHeroEnd()
    loadNum = loadNum + 1;
    if loadNum >= 2 then
        loadNum = 0;
        this.PlayerAttack();
    end
end

function RealManWarManager.PlayerAttack()
    local skillId = this.hero.normalSkill[Util.RandomInt(1,#this.hero.normalSkill)];
    local skillData = G.dataTable["t_skill"][tostring(skillId)];
    local skillShow = G.dataTable["t_skillshow"][tostring(skillId)];
    this.removeTimeCall();
    this.doAttack(this.hero, this.monster, skillData,skillShow);
end

--攻击
function RealManWarManager.doAttack(fighter, target, skillData, skillShow)
    if skillShow and skillShow.f_SkillShowType ~= nil and skillShow.f_SkillShowType ~= "" and skillData ~= nil then
        local effectFResList = Entity:GetTableValue(skillShow, "f_SkillFResource");
        local effectFRes;
        if type(effectFResList) == "table" then
            effectFRes = effectFResList[1];
        else
            effectFRes = effectFResList;
        end

        local skillShowType = Entity:GetTableValue(skillShow, "f_SkillShowType");
        local actionFName = Entity:GetTableValue(skillShow, "f_SkillFName");
        local animLoop = Entity:GetTableValue(skillShow, "f_AnimLoop");

        local positionDesc = Entity:GetTableValue(skillShow, "f_SkillFPosition");
        local param = SpineEffectParam.Get(effectFRes, Config.SortingDefault.Role, false, actionFName, skillShow.f_SkillID);
        param:setRenderDeepZ(Entity:GetTableValue(skillShow, "f_AxisDeviation1"));
        param.skillShowType = skillShowType;

        param:setFollow(fighter:getFollowBone(positionDesc));
        param:setFighterId(fighter.fighterId);

        param.scale = 2;
        local skillDuration = Entity:GetLoopSkillDuration(skillShow);
        if animLoop == 1 and skillDuration ~= 0 then
            param:setLoop(true);
            param:setDuration(-skillDuration);
        end
        local effect = fighter:playEffectResV2(param);
        if effect then
            effect:play();
        end

        local duration = fighter:playAnimation(this.getAnimationName(fighter, "attack"), false);
        this.effTimeId = utimer.timeCall(function()
            this.doHit(target, skillData, skillShow);
        end, (duration / 3) * 1000);

        this.deathTimeId = utimer.timeCall(function()
            target:playAnimation(this.getAnimationName(target, "dead"), false);
        end, (duration / 2) * 1000, 1);

        this.attackTimeId = utimer.timeCall(function()
            fighter:playAnimation(this.getAnimationName(fighter, "idleBattle"), true);
        end, duration * 1000, 1);
    end
end

--受击
function RealManWarManager.doHit(target, skillData, skillShow)
    if skillShow and skillData ~= nil then
        if skillShow.f_HitFName == nil or skillShow.f_HitFName == "" and skillData.f_SkillBySkill ~= nil and skillData.f_SkillBySkill ~= "" then
            local skillId = skillData.f_SkillBySkill[1][2];
            skillData = G.dataTable["t_skill"][tostring(skillId)];
            skillShow = G.dataTable["t_skillshow"][skillId];
        end

        if skillShow and skillData ~= nil then
            if skillShow.f_HitFName ~= nil or skillShow.f_HitFName ~= "" then
                local effectFResList = Entity:GetTableValue(skillShow, "f_HitFResource");
                local effectFRes
                if type(effectFResList) == "table" then
                    effectFRes = effectFResList[1];
                else
                    effectFRes = effectFResList;
                end

                local actionFName = Entity:GetTableValue(skillShow, "f_HitFName");
                local animLoop = Entity:GetTableValue(skillShow, "f_AnimLoop");

                local positionDesc = Entity:GetTableValue(skillShow, "f_HitFPosition");
                local param = SpineEffectParam.Get(effectFRes, Config.SortingDefault.Role, false, actionFName, skillShow.f_SkillID);

                param:setFollow(target:getFollowBone(positionDesc));
                param:setFighterId(target.fighterId);

                param.scale = 2;
                local skillDuration = Entity:GetLoopSkillDuration(skillShow);
                if animLoop == 1 and skillDuration ~= 0 then
                    param:setLoop(true);
                    param:setDuration(-skillDuration);
                end
                local effect = target:playEffectResV2(param);
                if effect then
                    effect:play();
                end
            end
        end
    end
end

function RealManWarManager.getAnimationName(hero, aniName)
    local heroInfo = dataTable.getRow("t_hero", hero.partnerModelId);
    local modelName;
    if heroInfo then
        modelName = heroInfo.f_HeroModel;
    end
    if modelName ~= nil then
        local str = G.dataTable["t_roleconfig"][modelName][aniName][1];
        local randomNames = string.split(str, ",");
        return randomNames[math.random(1, #randomNames)];
    end
    return "fidle";
end

function RealManWarManager:moveMap()
    if this.battleMap ~= nil then
        Util.FlyParabola3D(fighter.roleObj, startPosi, endPosi, commandInfo.high, tFrameTime)
    end
end

function RealManWarManager:removeTimeCall()
    if this.effTimeId ~= nil then
        utimer.remove(this.effTimeId);
        this.effTimeId = nil;
    end
    if this.deathTimeId ~= nil then
        utimer.remove(this.deathTimeId);
        this.deathTimeId = nil;
    end
    if this.attackTimeId ~= nil then
        utimer.remove(this.attackTimeId);
        this.attackTimeId = nil;
    end
end

function RealManWarManager.DestroyScene()
    if this.sceneRoot ~= nil then
        destroy(this.sceneRoot);
    end
end
--]]
return RealManWarManager